package spinal.lib

import spinal.core.ClockDomain
import spinal.core.sim._
import spinal.lib.bus.tilelink
import spinal.lib.com.eth.{Checksummer, PhyParameter, SpinalSimMacTester}
import spinal.lib.com.eth.sg.{MacSg, MacSgParam}
import spinal.lib.misc.HexTools
import spinal.lib.sim.{MemoryRegionAllocator, StreamMonitor, StreamReadyRandomizer}
import spinal.lib.system.dma.sg2
import spinal.lib.system.dma.sg2._
import spinal.lib.system.dma.sg2.sim.{SimCtrl, SimReadOnlyDescriptor}
import spinal.tester.code.SpinalAnyFunSuite

import scala.collection.mutable.{ArrayBuffer, Queue}

class SpinalSimMacSgTester extends SpinalAnyFunSuite{
  test("default"){
    val phyParam = new PhyParameter(
      txDataWidth = 8,
      rxDataWidth = 8
    )
    val txDmaParam = DmaSgReadOnlyParam(
      addressWidth = 32,
      dataWidth = 64,
      blockSize = 64,
      bufferBytes = 4096, //TODO
      pendingSlots = 2
    )
    val rxDmaParam = DmaSgWriteOnlyParam(
      addressWidth = 32,
      dataWidth = 64,
      blockSize = 64,
      bufferBytes = 4096, //TODO
      pendingSlots = 2,
      bsbDataBytes = 2
    )
    val ctrlParam = MacSg.getCtrlParam()
    val compiled = SimConfig.compile(
      new MacSg(
        p = new MacSgParam(
          phyParam   = phyParam,
          txDmaParam = txDmaParam,
          txBufferBytes = 2048,
          rxDmaParam = rxDmaParam,
          rxBufferBytes = 2048,
          rxUpsizedBytes = 2
        ),
        ctrlParam  = ctrlParam,
        txMemParam = txDmaParam.getM2sParameter(null).toBusParameter(),
        rxMemParam = rxDmaParam.getM2sParameter(null).toBusParameter(),
        ctrlCd     = ClockDomain.external("ctrl"),
        txCd       = ClockDomain.external("tx"),
        rxCd       = ClockDomain.external("rx")
      )
    )
    compiled.doSim(seed = 42){dut =>
      SimTimeout(10000000*10)
      dut.ctrlCd.forkStimulus(10)
      dut.txCd.forkStimulus(21)
//      dut.rxCd.forkStimulus(26)

      dut.txCd.onSamplings {
        dut.io.phy.tx.ready #= simRandom.nextBoolean()
      }

      val mem = new tilelink.sim.MemoryAgent(bus = dut.io.txMem, dut.ctrlCd)(null)
      val ctrlAgent = new tilelink.sim.MasterAgent(dut.io.ctrl, dut.ctrlCd)(null)
      val ctrl = new SimCtrl(ctrlAgent, 0x100)

      case class TxFragment(data : Byte, error : Boolean)
      case class TxPacket(data : Array[Byte]){
        val ref = Queue[TxFragment]()
        def push(data : Byte) = ref += TxFragment(data.toByte, false)
        val frame = SpinalSimMacTester.dataToFrameByte(data)
        frame.foreach(push)
//        for(i <- frame.size until Math.max(frame.size, 512+8)) ref += TxFragment(0x0F, true)
      }

      val tasks = Queue[TxPacket]()

      var txBusy = false
      dut.txCd.onSamplings{
        val tx = dut.io.phy.tx
        if(tx.valid.toBoolean && tx.ready.toBoolean){
          val data = tx.data.toInt.toByte
//          val error = tx.error.toBoolean
          val ref = tasks.head.ref.dequeue()
          assert(data == ref.data)
//          assert(error == ref.error)
          if(tasks.head.ref.isEmpty){
            tasks.dequeue()
          }
        }
      }


      val allocator = new MemoryRegionAllocator(0, 0x1000000)
      for(_ <- 0 until 1) {
        val chain = ArrayBuffer[sg2.sim.SimReadOnlyDescriptor]()
        val dataBuffer = ArrayBuffer[Byte]()

        def send(data : Array[Byte]): Unit = {
          val d = new SimReadOnlyDescriptor(allocator.allocateAligned(32, 32).base.toLong)
          val size = data.size
          val buffer = allocator.allocate(size)
          d.from = buffer.base.toLong
          d.controlBytes = size
          d.controlLast = true
          mem.mem.write(d.from, data)
          dataBuffer ++= data
          chain += d
        }

        send(NetworkRef.icmpPayload)



//        val descriptorSizeMax = 1500
//        val packetSize = simRandom.nextInt(1000)+1
//        var left = packetSize
//        while(left != 0){
//          val d = new SimReadOnlyDescriptor(allocator.allocateAligned(32, 32).base.toLong)
//          val size = (simRandom.nextInt(descriptorSizeMax) + 1) min left
//          left -= size
//          val buffer = allocator.allocate(size)
//          d.from = buffer.base.toLong
//          d.controlBytes = size
//          d.controlLast = left == 0
//          val data = Array.fill[Byte](size)(simRandom.nextInt().toByte)
//          mem.mem.write(d.from, data)
//          dataBuffer ++= data
//          chain += d
//        }

        val task = new TxPacket(dataBuffer.toArray)
        tasks += task

        val tail = new SimReadOnlyDescriptor(allocator.allocateAligned(32, 32).base.toLong)
        chain += tail

        for ((self, next) <- (chain, chain.tail).zipped) {
          self.next = next.physicalAddress
          self.statusCompleted = false
        }
        chain.last.statusCompleted = true

        for (d <- chain) {
          d.write(mem.mem)
        }

        ctrl.setNext(chain.head.physicalAddress)
        ctrl.start()

        while (ctrl.busy()) {}
        for(d <- chain){
          allocator.free(d.physicalAddress)
          if(d != chain.last) allocator.free(d.from)
        }
//        dut.pushCd.waitSampling(10000)
      }
      dut.ctrlCd.waitSampling(10000)
      while(tasks.nonEmpty){
        dut.ctrlCd.waitSampling(100)
      }

      dut.ctrlCd.waitSampling(1000)

    }
  }
}

object NetworkRefPlay extends App{
  val cs = new Checksummer
  cs.push(NetworkRef.icmpPayload)
  println(f"${cs.result()}%x")
}
object NetworkRef{

  val tcpRef = Array(
    0Xb4, 0X2e, 0X99, 0X93, 0Xbf, 0X88, 0X6e, 0Xa4, 0Xf2, 0Xcb, 0Xaa, 0Xa6, 0X08, 0X00, 0X45, 0X00,
    0X00, 0X34, 0X86, 0X5a, 0X40, 0X00, 0X40, 0X06, 0X30, 0X50, 0Xc0, 0Xa8, 0X01, 0X65, 0Xc0, 0Xa8,
    0X01, 0X64, 0X14, 0X51, 0X90, 0X5a, 0Xa6, 0Xb0, 0Xed, 0X23, 0X97, 0X51, 0X98, 0Xec, 0X80, 0X10,
    0X08, 0X10, 0X6a, 0Xf1, 0X00, 0X00, 0X01, 0X01, 0X08, 0X0a, 0Xa8, 0X8b, 0X07, 0X4f, 0X2b, 0X0b,
    0X3b, 0Xfe).map(_.toByte)

  def hexToBytes(str : String) = {
    val bytes = new Array[Byte](str.size/2)
    for(i <- 0 until bytes.size){
      bytes(i) = Integer.parseInt(str.substring(i*2, i*2+ 2), 16).toByte
    }
    bytes
  }
  val tcpRef2 = hexToBytes("000acd2c1594f0b014c32d6b08004500007cb29640003a066b659df0113cc0a8b2ab1466841ad17716f5337cc81d8018028f5f1b00000101080a21967e34f180b89b170303004381ca9ca6cdac7600bc1fdeb0e5c219fb432dc7619bd6416ba30a53b8eec7d630dda6aacd820d834dfa8dd7437991b99d0fa5358176904d1beb521b06a6cb09fffdcde0")
  val tcpRef21k = hexToBytes("6ea4f2cbaaa6b42e9993bf8808004500550c4583400040061c4fc0a80164c0a80165905a1451960ef2b4a6b0ed23801801f6d91800000101080a2b0b383ba88b037fefc5c2480281fc66d170fb91e1f684889cb6972770d97bb83863f13004d77afaffb08c9aa5b1bd1c5e5dff56534daff9b2ec3fa0f36f60c146a467de5021425ad408b03857eae4c4475a22b0e6ffda4e26e97faf86a7f49e93f61353791d782adffb0f95561f1129297f3a9542f20f1ad8a936c1ea32b724eaf4ea7765c876dc289861dccaa8e4024d0aa54d870e1e87b5cd3123515e287bf15fd52a1e5a962e47117aae1916bcabc1a9c9789daf6a151db80b1c2b81f7fc300fdde25cdea05dfca25167e221ceb36182e50c5c8a1204b83351481885a4da3a46ee2531be669ada436cfeb77d42abb7a7ec303bb3a112132d2e30b64c2cfe11964d77671caa889e3a773622ccc2d99fc40f6c63e6bb5b3cd6a97834a395791f270dcb5b41e1c59f1cc5c95c4c0891757469ac8de1e1c6305e3c80836127d86d9a937c18396f00bee1133ac6fbec2fc3bac0c0381b109397a294d3ea78cae0cdec568236fff9ad7c7de088a69cd0fb900bb02bba1c4a365e5ecf50e7e093fa7e62091e8e65438b915962b2f17e4664359c6ee95d243a54e4736deb532e5b70cec5327103edb597b57ae60d4d30cb8b82236c1faa8591d12eaa2579eb88daca26b00e79d7f1d4398bab93fd30e0834de7f073693024dd4b61d9ab8e7d959cc56a57523a8bfcfe0b52585dc592b29b3f092872c14ffdb7252157b577f1d9a0107bade5a014bf39c744de0bc2dc40a1666ca51c1dc5b97fd7f2aa184c1c980562006fc9a45a229278abfc94361f00ed710881fd54128d1c20987049a6d924dcb723a2fe6a108535b917d78c4687c42205a7bce3f0a1413131cac51d23a26aeed59e1f586eb37a1452f7a6fcfaea72d79d6d0610ac0de8ba46006783d3ff26c04b72c6f0db3fb290fec7558ad3a18b4a96bf53867485a2c1bd30065f3eacbb1dfffd5b408be7a95a853bef83a03bad550195e6246617715fdd98350a1e75a173b9f47e121ef1e14d6844ec83d2000ab67a89e19fd6391aeeb3b205a2f806ff8ec2868cb4693392c9102fa9d1f844a167210022737bbacb58b2303ea9acedf05a9c8ef127ea100b9d3febf6e5bbe48149c8eed6cf1540f398bc36d440aa33b5c120b9b3b6e0aa01e16f5d3c51a47ec7dc3d460f7ea116aa8ac55dad050200b57854f0502a41048b8dc466a2a7b2bca70d69f9a5a0731a96780edf46be7f1ce44b1e72559e3545ae0fd32c51b26ca4fd9415d1335d0ff66d1c360241c4c8e310946aab51e99077714918750665ca1f472ef32ab463492a1da923ef67931acf339ce18542c342c46679344efaa4454b03b348ae2998a187ccac55f199c53d2c75d1f077f180e691e5c6feb92aa3f0b08a0a4beadace4ae1a17af1933e71956baeb2b2609cfbd9be36e3c38298368abd4482496f6e0fb2e28bb5d0217a9cb0f09b4a81cab8b4741465078b6f69ce2e2a2d5ca9af672fa29f080d2b159f62b553bd58df4a01bdb0230f702c6bae80a3638181dfe44ce75cbf500d78729d52ceb88cb5dfa3eb06a1bab55f2240f1cce420c9000753950fc06434d6b93c3d5ee78329bb43b24d2b691acc2b0714d58a978cc8dadf7bb06f465b3c2ef1200a68efd17834727f63872e70336109d76034f590eb2cc57891ec80b0b45518b4f8ddb013688538ecaadce560ec7ce20f201b9d73aa81bdaac558542dc96a1b9d38262045d28b44edf542ab5b6a3ba24cf211e4f2c4e2b195e0c94d7e45d0573c4a177e081dbcf63810dcf8e2ee01fdfa30ab4b5f2f148cc2107ca60b1449440f4eff44478db71c69eff373ccfcf4e1adaae7c1da5c1e2ec8abdc265ba0515bd4e1effbaf555a0c718044ab003345454f0a9867aecd581f3fa5be02b2c180afac62460eb19cbac15ab50a16b6a9d290a570028fc4c8320099fce1c80030eb0d4add689455b3cc07dff20a829d31759ed1c731274dbc973c8719f20680568da4ad7fe08d640f0b83cca6dcaa0c1c61a13f04a6db840c85d20e5217fea4ffd61e74387fd2e9b9d09e6d2155ae7ac9fe04a47026cb42dd5edbb1973a1c035984a53f15c592cf913e524fdf9326cb0ac378767130841995d53413b4c32aa9a12edc9e508c361d92bd3848e3e481f9ce8e8adb832dfaa307ce5ba6eef51e6cf92073b1c33ffd2d0c1a7f3c4c52a33188745d8cda8985360fa67d84be7111eb16ac6d5e4c3c814e25f45211ad3760cecfa0e1e41547da7bf815d5b9bbca6e9e13f252337c9ee85f7e0b81e5ff8505e3c9f941816cf7cdc0cc7a98293110a6d01111ec0027ac2ee285507f79a412d88074fd183b2807da9e9183d243334c70e651fe554d58a7ac6abef74ac17dfd51d91ecbe2b4857dc8fa4b198247c94991a7e3e459090539aa8c7cace914e7b1b78478d1bf9202ed4fc43e32fdf779ffe8841f361dcb3a1658a18eb0a62b81bc4919afad420bb56c28120aeca26dd9832c2e7ccfdd12e3391831420e9890e2dd918c1e7480a8cef94457a24bdb24e77f03f2e42f96ff8d33fde84160d31754bec558ef5e77166c39df7118d4a798ad5155ec3671a82638636afb112c7003006449238b4b5ba3197203e9671d518a3c7dab58535256c392825713aae391b469150d100ba2c7c5a60dfde777486732375db0595c46fe000c9471410f4a9e0a2eed4dfe419cc8861eb662a792adecee946e6e6eb23851addea15cbe758a1f2e1f829382acc381c94034b3e0b862b56bd8fe540e61d2fc5a0d6d8fc9cec7f41ddd40a808e90d0a9c8dc35e6848f7835132bcafa109c6d91321f88312ed411174664cdd0cf7f747e944b2be5f93a41152f818c9a2c75b4b404f20da4b64aa589d393983adb96565d1e9651ff7a32b1f52fdccdf5552f2d92bc57f689a544281e07269b77ea77002ef95b9c24b708e91e10b4e16fe4641736269ae53c7456f87ef33ef013e4244c4a30623b552cd7d0d2343e186beb90ed7d20c90eef9adc08e0603c0d760dc23246517dfc714d0cc09d709cc3e8a2b54067d95dab8ed79331213f1d5e0f750889e3e367bb4907f1934cc097faac4009410c7740a7259f8477949ea51363f393c630b791b16052fd55116c5bd0849728c98492fe098052d38611f3d1d4e530b2dbf8fbd006a52ec3fe4e03636cfced4407a36137bc6a7dd61e851ee99150d236e13ff23fe0c9c6df6798ed04c7a8d633e90d14d145f03e31e6eadae2b02176d0afe31e8138cce46084b91edc57a5ad2f918be5f88143683c1703725967194b823880c5908d87688f2de2cbfc1b6256bc79973da6b0bc85d4e5c284c5a3603d6ee69938750cde9e47c2329709a3e39e5c087ae2ac4d8b77103bd55ae6b3eb4372fcf3ae4f17c831a85a0c77bb2fd2bf943bfe18414ba0ae32ac022702d50401ce5c7bbae3ed117f2f9edd26a4ca4384bbabf14a5f069bc00258934b02746b821cccbfea692fe3806a73e0037074235a1745e1f63a7d71c8103c6bb7b7dc62ed9f60d986dc6b154f7a037d0a4662f12b9c504e640efc2442e1a6c34920749fd8e5de78b5e5910bacd1e6c7c8f61d91902baa6fc48ee500b1201dc9725f7c9630dff96535b9bf2df085ed0febf92bf4144ef8dada9fb8434d94124d1e53f6592065a3954e7bfbb9999ceec3378638cd9d204819992437900cd94b8fc0d46a52ee5c330836b0aacc1ef2f47631e011915d1f98e58b5ff5fc66e518ad46be47eeeb2c6df3ae576b8ebd1d2aca24c2e2e4606c632bc1f0ddb6d7a92466f84fee12a4ecb095b61ae6014e3ef261fca056e0e2898f9dc54526d18935adcf0acb7c2990aa1be64b51d61454244965a5fd0a4a7ac3aa43d74377ef427ac85f569331d7e2deafd9d8ac858200788b62d8a504b4ad840af81e310eeeac8f052984cdcead0deb03bc75c104500f819953574027eec833ff779879e1d8b589118498b37c076251b86d12de4289297837f3b2f71dec056aae6c180d4de1b42743186474edd31791cc9f0d80099c1b5ba7988f194719ea46f856f860afc4f80f074587fe93ed83646101269528713e24390e126ff962cbcc72c1cc4c4d9cff11e298a0b363e5ea70a1e4065618a88ab112087b008cbdcd3f77f6efc6fcc27c696dfb4d1aed1d25899d82065c3575833856750bc2626529b74fc73e093a3c719109708361dbcba71bef3dbff08e1b05dbee3e9a20010c2407feb4cc84d09b34404710649a1a59c0895ccc543762ab5105f13fddf117b768581160b7cc4be4c1f4a17361c7d67ec9a7f9df3d7bc51a120953141fa95325c27318816b0409b2e93f5926051401d99b32d97fc0833722ad26613a38837486f12e289eee00f33937b63ecdfb355408088dd3304d99f0ef61af10e6eb0a20340108439b618ab2f40160b517f633be0c1826a40344bd82f44f47e783820b8b2fbc255f05e6ad4560f8f6ac027701e7f281842aa1557cd343c4abc6774c13f2799f38c98a3a08af4fdec177b8f0b04478e7f9551b4071094880e77f0617073ba21446790fd289dc4b5db5f9dd495ee86aa55e2c385c07705d73cd1fe5697ddfef8ff21aa92762baf89f4c23a0fc21ed24b3fc9cbab5e1d47e39140b6073eea0e8ef9390e34c146e14a52269ba10a6849e8e8bf810004376c145f289553785f6070d1b40b3a9ce69d00d0e5149918390193053b4a975973c257042e6284940e04aea81e68dad1b2574037b0ef500e750b701f648866a92a086f4d19bc1434a777c0855e50c8d406a0228c4ce536bc17e54c7c4724e48b523eaab8a0ddbc471c3fd064c1efec0fd6692224d26edf907fec523073d5b6e3aaae8723054b074dd8005b2448a2f528e91028a79dfca8ba1e7fe3288b300ce5137338a7e3a0e10a2dba9a3509ee5347750616028d9edc9778b491599966201e4ea616409f6e5308e86d522c4e3f6a69bf108a3b2d0549e67c56e792dc13b199d0c44bf73693dcc5db22755793e2161bff1d90def7d42574543c372a604d09dec477a76f4e1d9627a71ead22a6b6da90ae3aec32b4ba00f0cae6420ec9118064425702d19fafbcc05fd16db3140d5e7a27327acb9697f27cccdf2eeed3552c07398b78bf1a4fee6d53338c7a2cc78f34347a8b93564706cf5c576ee58ee5cffd8af33e92e07b1cbda69f4d1d50fc5290dcc7c5df7104abd55e709badfd2a9a27df436db4a30b500f2c525837787b0063220e33724f3f4fb6eef51924106db3e51eabf5b439e60728f74edf54ba48c5feef918cb5bf320331dae608712b9b9117f44b06c8b865c51fe376847739fea1152c655825e6117be8708a7f9ee43b8b0a5e8a6093a1b2e230fbd760b2f858ad22343ce57b698b55a3e6b2225ca2e787750ae21820eeee6f54d7bd332623cb5e936af1d0ca9c6110c45c1bcbd339fd68f650d2f534d7fcfa06f623ef50a00baa7cb037d67db2d7ec83e9dcd53a013902d2c994efe26f04582f4d47eb44476d100456e2b03f4b3553025f9f1eafc7b6f07fa6bb15aef979cf80fdc16e3d40954d0c245eef428f78ac0de269523d39d71c9873fde98998fa95c105c36edf3e453a16af4345e253eb9e0d636131abc8da01ef7691add3f9c85a2860fcfe48d137cab7f0d5016dce896435212db5e7c5352a8c1890bd2320ff6309e60f5d2a8c33f1f3d58b174373c4cc993f511362464492b3de09937c8da8e349041ae2f63c769952b9a5457b359ccf837806da8cac8c96f64ea14af0178586cc93ec8b910413a6afda4233ad6cd8542bd2199a034df2f2bdbcae970c26afb0e951855025e7192a95fcbf4eeb358f1873aa74e8c5a3ba21e2ee37265d558bd288bde1c5f6d132ecf4dc956b390769d666415aa3c4bf787c80e2efb2177cabfc31e1b80de5b8885b3f1d12b82d54539a45ad6d7431767b7ed754c3341ec986d193fc18bddb9ca795c7c3bcb247f9d87a16e5fabfea052084483bf1d43fc37ef70f8aa0311ec15679d01ff9083ab2ef7e9257981ebffb5bc59c3fcc80163756a2676d5b81e1549714ceb1ec31075264078ef9d38561a149e7449dcca623bbd3c4871b7777c483b87511a5776f75be1d9c5d9c4347cbd85b3a4e6383769c25f523705736ac3dd2ab578933c868b1b94646b9d71937c9712912b5831c996bdc5d8569913c1e9ef42054ae1589bd09284b8037aaf1f1d58d5e64e81e576f0d2e2b5d92192c3bced6d281bdee2def85f82b725df929b92aaeff142436155ed1557c3d821af621d3170d4f23328f6c6145a79a46c18aa4560bff089ef4475423dbad543471c643c48761d155a4087b82aee0a9adcac9ae7bf2305ac3d318a3c8cc2cb8a633d763cb9979690f1bb58ae0519c7fbdf5d1049f605bd15f7b607859bd0373fe3ce4a9f1bcc555ebd19c69d14b4d31926db034f4a9cb27c85ce630413e6f09ad51e1e821139f8a787d2e103f362b482813eae2c4b3f9731a1433b35b744c2247af684511cee90ae046ff33b5ad2bb87a0f76deb18e760564c061ba6d5bb114396a9dc276ab219d8fdff7c5210020817a7ec38108929e3c056d4c3272d37369cee5757eb9d7cf114f9854467d7581092e9d99dfeaa95d61233f099b27d50eb4cdc65bfcb2489522ebc402af827a5365262d039395bfa21992618d005702deb328bf55aa94a93ce4700ecf7d739d45580430dea52777c71d864d4a34255ec378301c8c641dc5f2ba28fa9aca686d1e8d720a0b014988ffd92fe697e5ed2d9ae95b3c98c6130cb2973b87d7abb2297d6f1c659bd0a41079b865bfe3ba7e7498a9c3b1114c9a4980f6ae633044bb3e2ce82b22ad2bb21d1091cb5926e532f258a36e707f1a97babcda6616eb5a0373525267bf3787e210e2d650014c8aca896217d14b757bc15793e055a6764c2959b8dac4a37ec3f85dbbaed481b19407e267106d2dfb2608d5aba98ea1f218bb192cd9c2884226176fd677321082dcf17da5e42746d5a23b537b551b044036c12bb97329b5b276975eee7d3e27b28afa30a00ccc14011c02ab927ff84d3323cef96fa6c729266630d16813b27a94b8411590178a4a9254cff0d9857ca17692072e1c1bb79410cbb4650b7b71d42949591a036ef23897fb5dc0632a640a4feca6d4f6cddd42df2f064862193b950a1ac7ffd299d16801649d7566e2221f42107b7590c22e0959adae0e2c8d590ed758d44c0d129b74c12037b5845bdee03db1433bebd03bea5988bee630e2f82da289d86dc031a3bec7ff58b9cadf925c97576c683a5cec18ace14ed0051aeec0a7b1366f41c9b676aaaea6fee01a6c9d8fced3449f173c5591382c86d4fc41bdc2976818edc6a26aec835f0fb13d409caa810914a0b20752ad5dc857753b4eb0871e149fd5f3a2c9e3e34cf7206383268e27061d453fd67ad3515c62ef15e7157a067844c883de80ea0224a2d3b9df563e858ab310cc51a889c2b8c2b08c7b690fee8922fa34f8d39961db4b93f5750896c90b7583fc4e71091d0bac0cb42913a27490f04547f3b59697fb35bcceb11010c4698bdf7eed0dee8563b94c08afd96e0b708d0fa8f091f0a030e1afa4902a3b67416b093e03cfb06c27c0e4a90a85d1bc3b23f80253d6efb4316ea56d0ec245fa1a02f3263b3f7731083a5e6d564c14936ed44efd48ba88239bf3df87805a8f45a9ac90878d50ef1e5ebf73b54c7a13d0b865046c63ef547058c8d763dddc9e724ba7747b8abd754796ac51f68ea3cf2e0ff8dc06a364c57063b64f9f4358f5f538ba35863bf576ad4fee28b5764891bf513e5652624f58cfc133df3834377c2a3d3f479e2be9a40e7f7be416f6a3758c17df54bac4406a8c7e1ba8e813676da9f33cb22efe38741831340f15c9faec084616efcb39a85278fc4e289b439e0dc6488ec614cd566872272af1706ac22aa630b7f49d2cd989f7b0d97a00fed8cae73ceb2d3ddfb51660b0bf3a7ac06bfab5ca7b1c37f5d8835ef32141c9268c368da22f95c1fec45caf7069dd5da780373a74208a1cfda2975c40f44545982da05c5b1c834bbcaeafa60ccbbbb7b27fe286a64a2111de7d352787cc2d7777973326b9ca200f89be245a0deddf87e8251a195dc56da1dee3d4002bf1e0fa8c75fcd30b11125c1f7231bdac0ed47de1e0f885bfc961c37fc43d9cb541326efc1b693f413e81390fcd985332163fb4f6f17a3537c0be4e8d016089fa56265f9647e2cbdbdbf5c91315cd03cb9c9560007f1e09dff47f6a12f3e584bb19c39931eb512cbd1056fc5ac96205735e237ec81de802840976a1ca14aa6f75a10128946a849955f198292ea10cc337be8b9e61357f9518e61516883bdf729ffc349beeaa48a2cc0bab70cbbd3cb5abca39692fefe58cdc6053d286dea6b5101e215aa262184745a73b387d3173658396b8ef1bf9872f8e7a2578f4e90363095a5c04b6d1d6b529b8fa8946ec7b0b8294ca751dae8e06cac4c519048c88de580047ac574cd9b070e88e0c6774342b10f895078b0e9e0c658779e698a2f660e58c493a596ef2f1af4fcabfbeb03c49d8b60adbf4508870230c15ee770fd151ef75e9799a39cb125a8e7346e5057ad894efa8fd46aff50cae438c82ba470112cb5fec4c48bf1c71758aa98bd7f076180c4a1d3885ad837ce2451cde3067de7b93c59f9a77e2075bfbdf93066dc8a161bdea4a1df022d3e9d909fb185b9ded28e903970e49727a78ffddca2463446f1e452e0f327c38cbdef07197ba0224dccb9910d89caebd3dba1b25c249f48979579f66cbfdb96503f302326baf883c13c7465e4e39d7abc7ee3f238fa063c1ee1e9d3b0cbc189d450894ed3b091fdd84bb8bb4dd29dc18fe98fd7b2f079f2a30eff750db3ed8bccd9544f7a74e166ee19624c75cc0366c75935e4e536f6bf0f1a5e2e6b261a7412ed446bce2a9b2c5f031edff46dbb7250beefd38076c6824cf69c76d345b780da467a4862c57d139c40917e05abe3443ce2d3184a252c2009fd354e5af5a54d8448075c798af78d0f4b427c6d318a026a816f1fa994d05093cbafe7fc13cd4760cacc94855f3cb38bf0de4c34aa40bc9ec6fb114136d174fca8cef9ce5a02e1e7d2967098a34670beb34ad6960797e70bd393162f551cab2833431e0db6462be354f7325c735daf4821b0a9483b06d4106bcd3248cdb80d432f831ed701d0f1e25e88e73199be14a9447f72028e19f8d80efca0344be242630ea6e082d95d1f3299a6835a3046bb00006aac014648764c885467325ce5fef2788e261da88bd0a82ef5655bfe2c5c03579412d5d2680dcde1123f3f67c1feaa7d8a2ad85e24a841fdc1a60ed5e1a70088bc6c229855e60db7cdcba67848677d836f23636078823f60dd749c9923095915baefae8b7f77143fa1044a62524a5568ccea12c2db41ecf0313cf3c5d98d8c1ea94c8fbb015568a3c10b6f55d4fbebdd6943749f06192dc6bbaba882b7c5adeae8bc41422e85a2fb2d95b0b8c35d65ea4a41505d2c6ddce68b53e124dfc3898b4e9bcdd2aeb420754fcfbc5b27765603cf067be96c740912fe3a1fe5eaf128e1efd40c33ad46e86264c8a670a94c3962ee3ea8f2486b646043443f6241ec11be24a2ddcbab800a319a5fb183674c35e1d1191ca77441d5c9ba4e6f2ad8d4c445b710c0de8d5288315a9eb88f88f3994e32c5212255414dca2be65622396a2a2fcbc49d1c6aa0e4b3be17ffeb9fcb59c96d6b55454b7978b84e96f6c839c33de1d013776ebea4efdfe01b71f47c3682912fa160ec7f8f238d32e966d4cfc878ede1bfe26b84cdb2aeec25a514afa8effbfd98c7b1a9631f57e827c11a1744ca279db98ecb7657cb33481a4b5d6e7a113cdb7cf5dcd8d1740ac053745c2c912b9d3d91907ae382ac804de525dd9817aad6ce1820df5b479b494cb8cf97cea119c2c97d7024478d9d450462a7f2bfc7264cbc734381d6e93a8faec7dc8642ba73575a7e780c7a8ca19e5eb0a14dfbd1158744667e8c55be64248034e264cc035f1cfc66dc38ecf409cf161c0af36b1345745d10d7341ce7c08aa237179f6d3a58ce5ea6bf8f2783e639d078ec66deb669ce456c67e178ceabef5e45d4af1d53cd4fd958193278e6338a87c5a72bb912e87f0b1078d2e005e765197aa2f3213cb711f6b2faa7ec1db7639dcbb30d7021aeae58298267907fa4947ed7090e33b9da301432607c80a640a72203e5d204ef6cadb3621bcea9d53044be78bed53b474e635da7a72131226005442319f7369a0a8b6bbb789fe2422966ff86e988b0b4e7943422d8bc2e02c45efc1ac1da10e89195919509d5a4a2f3f87b2e324b1a7b37e056709fa2272eb89fd15eea78f4bb8a9b5cc254433db56832dc9dc42951caf1dbbf8e77b2be7f56847f24746c2b38981d168810f8fbe98731d07c7cd064480a2043734abc4f955616dd4d0d7318e4f45e3f5ed0f38bb01e3b7bce30388cd531c795a15bed9f5c999cb29ef9db0a90fff595105d9aa34395719643a0899d40c9274af6ee09e8cf88a2282b8252f21191f1f5de9c25a4d7b5c2d0afdbe65f4e9037be68973c2185701be28dcf3e0a8e305fdf88335e0f604450b5a87c125382cd4b82a0e9fc707fa463bc443d353c199bd94278e6cf5aa626fc4ca1c8c64b3ebaac5fe93c6b8e4decc27ea5f91f7c277be5001cbfdad1ac145c65306ac41d785bdb1c727587511a292f798cd7792216351c29f22a02f2ad7bfac76c11d50ce45ce6f0fc839b81a0d8921a0337ae746533a5e396681e8e51784ee0c429a5c57627ffb0c7473984b6e3143e7790a917fb5b1ea3edc821bab35c58da2a9db0d2b1a7b734850a3c7519acd2a02537929f19ef2d145b95b84b31018b564d38188cfd75642cab83907abe2e5b4a87221e69c483d5f48292c0f52beb3574e39328c01f9b6661596b171f2d4a5918a2d7238b5bf74af6edb15deccfd7a9890132faff0366719086e4fa1ea4b14966ae62d4a63ba39fa6a7fe95d0896348af42e013ef1d3c5247f5fccad78ff7f6b503393240acf186044b9605c82d1029e0e02c11e66d931aaf1e24ab64a43fcbfd122b8471b404823c6f17d0dee8290010622c6f38504c8a570bc92d6dde5d05c0ed755d99503b8f2269473bdef1eb48694432219183693006c2b8d586ba4130e1ff6d13b4e4e84cf4daacee8a4f3fbd98290a46f0ca3659aa380691760dfa15d6a962fe833b42293182a93de4c729ce4b9716112c723ada490f2e49f45b4a569104339cad575f06168f709eeafe659484031768954dd632f787b84318f9238dc87ce90a5bb8fcb3cff7bb6413152b31405b7d62e91c2972c57db3f62e7753a9ec41eeaadc3c8f467040d3471edc8884856df2b2112fc0185783022463b64260eb02a883bfe982eb21e83664670ad6d530866c13f2d39ed93e9367cda4a8a4189990709e2fe05410052d9db920d787c48ab1aca368dd327b35a4cadd01d54b452b0d87324c7770f7ad4458501f4f87b7fbc53c7c341157d9a24af06b449d20ef9f02a73037aa92dcbc95b2fe78dba5fe9dd2774cb4d66aa2df891e48accecbd747c9a2d184d17636f6904b97a6762a04efad499e387b8d2e80688a933c3f03060c2b6556fb62481329a49bd86a99affc0ea3b1be859a71cf49134d5c57e0b326dc73194fb2f6af419b2bef60bb3c2f356453b92949fd3edadf7fdeeae866a89f4137be6bfe7eaafb0ec93216f521def962a1d8fd8646e3b732c09929e925a2149dcccdb649f44738dd1365d69654e498cac46e373400126997617bccee0debdcacbef61cf891e8b4e187ec5bef523ba761a66d3d6e175fa25c9e03bec7ec142b30a5ecde3c9163acf998f8e07b4b3fa7d3e91627f2083349de6615e676e7b11b96e8b080e52b14e513ef9b26b327f55b771542476ba4400734d5ad44ffbc6f29e9f545261ac81ca458a244245c59d18fe9c2ab979517514bab9d0f68c233a6435fbd013a593546d8f4c50f741f9c070fc72ed347d0314618ede7b93eab1a5acad86df5d22e7b5e8607b987aff83343e419a61a2289776c5f8b39d471a813473b9c780caa1cf0d82cdfc5f9646f41dffbf2ff4ce17527305459facb9fe3888ddafa70ea178f507227ca5d1e1e21b05fe7e986cb1e6ed462bc7ba3126d671f6aa4b7fb80db5a61c38c7a3d13431f6adeeb3c46f25e4eb73deaa2699157f7b2c31d47871b935b0db48c3e3270251472d8230014b6e130b10dc0d5d20bab8b5f9a7bfdad91c1224ff4a541c86f12adccf872471233a384e4d3a214bbee4f0747fb55396ee6c29f7d706b204734dc84bc424a6d4bf4b5718b79fa0904433ade62c0e214ebc258ef4c4e725cfda47c984cec399fa57e8bd7b1573aa12bdea62fab7f871f66f2077c47f04cacc0fe00ebd1f80e704c82930b86478a35a8634e2c7baa639d598bab289938a6c8c8e166fcf078990ed9da48b3310d561782115166f0b9e572adcac199987fe61a944b337b957766eca5f2172b73cbc23a31cc880cddbcc9f41cef1bc9be3e41ba5241fa12f4455c0a14a61e585ca08b92f9bdf0688f5d3b6154f14c802f945c193bd60e28e23151dfb6ec7d87433d7eebdf7f29efb31059cb1c657238816cfa48a1d40768d833b3ef2f9a8848b958845695d72447a8f32c75fbed3ee07a80c46f0db119f13d6f336474e3275ab4b52021d5396150dd85f13836842214f914c7465fe963ba1ffca6aaea11c8929296172fc732ed642e247a5470c0f870d925d37e56736dcc6fb84f282f4aef801e4dc5a2f66cfb900abd34cc9d3ad4f8e59b2dbd414a46d781b5f14abf4258680a12df5ee42e904bf753eed20da9778d7bb6d9b26cf06365fab25430456b5b8855610c1fdc32630769caa2f1ee23dad863248d35db9228864a7df3a325cfe4ebedbbd2cbf0b38c78765e0c5741c38441c7250af7aa2a0e3806c928e98c656dce20ad6b043981cdaaac7b651f8299fa1379fdca233b5e585a624f1176c5dbd717e9ba5c072eda365d85ed7ad8ec681345ff1746ee9dba6626487736aa4b09d1a78245f27706cadaeaa3bbf327f7cd5285dbb80ef4059eb918ab0f85f4c0b79255fe00ebf4674a80e2f69b7d40dab99e3af227b70e3ab648d05ba70a49af94b277ad791889f6898b0244a85a96b7256d4a83cc8f4a904678d173f5416ef0f8541b7193ae26d7dbd465809a4102aa0bdaaae644352cced28d9c9d3b3233a5b84010a23af1f6068d8c4bc2899a7fcfbb5465fe66022fe4bb2a3361f601f0a34ff73db0b144216ec366e9976a38cb4364727a977ae89e1efcd498b17a9f2b2903825176a397eb6a3eb7cf34485a2102bc365ff6a6bb0180b5baa17ff7bc2e1771cca1c5527d7cac07be87c62298605632ff27e99fd91252244e0fcb6e390fe3b9c4c55d636d958a31700a068f6ef33c141815758b03b6ff7f505d98ecc75af12ba68307d06118962fe6b86ac15dd83b8616106be7a64aaf2d6911b38e44581c4b74fbaf4c35bb47ddb2f5cc5bf6102b669e9029fb3a6c1cc69e6d1bcb0fc7b0ae759d1b783f260baacf8ced0e8a1368bf01241d4018ee35cbbd5d86d8b3d75eb2b1a99e66ec25e669f810a25fc01672b3164e3e5191717a20c91205ee0705c9545b5a51cde58b16edd90de69a03c9164f3a80d83e19cff8b1dacae5eaf1ea3b48c2dda5693f6251f50d2c766ce79e7fdf836ee4012ad9a51ba0f749e29588e46c03a7fb921287804896b510da06a5b87cd431a11beafe827c9dd77119f5984bd5abc6e780eea9fcf0816e8c5351f32b385242a053becb1134839ac4d201da27ffc07e3152f8347210491ba08554423ee03c65a7446de9780846cbc4ae46eb280ace0c11b6f35908d085d24317dd01a28aa13fc9963812c3894c9c0ae522d3148718fc67cb8e18d5a547d93deaadfcd955337483a72567733e602cced99ab2d5a71db1c93ed04dacfe4785cba4317fe0a4f38cc6182eb3dd37a998a2ee6e76142c63c7d5ebb297cd9ebd95735fb1ab2c5b74747493fc2263301e491c8876e2346c0af70927625971c02d00dfa455ad1c90c99fd084211eaa1492c36d98e3644cb8aec57c0a82f376a92326d0a6769c24ac9ca73a687ea933f88fe5803eaf559c3677ae5af68bfe6f828aa18f3f6aa24d43b122a02ed52c35a4e86c99d12d775e137b4a5b7fb9217e21896291cbaeeb3e59403740d775d7deef16bf450e339ef8c15000b641af8487d930ed7f0ec8419b2e678a80dd0e5fab0729dc0fde4701b081da6b8ee8c61bc1bb664adc0baf8cc339a9f323da82aeaa1b3cb99710ea539cb1b41fe70935a1857d8b7e31327830c557760387b4f15ba9b297cc1d5f6f5861885038f188b137c5af1f790815ae3baa58215a8475dc6b9e7995f176febcfd3b48b407539872af33d3249c525de243812f1f216e29bea5c904e9efee2d6c7e1c4a676fe5bf88ac3c83ea99bc4a6fd50750782b23ea80333481f39d82c2bf306e7e26d3770a2d5a9dd84e96ec8ec05131008fa1ab65faf7022b316e70e91aef04b17951838bdc890e09e3898c771e0c728dccdc084e6fc9a37640f58fd706ed5e69d062d773ea48af6a9f777582cd6b2f6481476fde82f4038ce9a873e7e31288c3deebc057a06b4b2cbe034dc5f9b968a6822d8da88d8efa0793f878e646593479fbdf3d8f39d4da2ed08d8c6a1500761be53e00f140a3b925f49b27e2cd539fa07e15d6b4598bae33145e7d4def22ec91f5c81f529ed6839cd86d495758492c00549c839540705449ab46739291163c13c7fe59d3b23b6c489b96dd596680538c604e6ccaace08a5e3882d4909898e4be88335a2377bbbeca4e5e2114e0ffdca81554d33ad5a24120ca8f673538d485df987f6f1fa25df8828d84f57fdc08be80371e1b4c71b3f26a5209524b086868d20ac6493ce4400315411709c3414a599b9c6531a4e927d9dac2ac848f1670749c972a825e4ee1d2235963cacb63ba6c0d8c69990e889cef2dd6a3d9d99e592b5b388ee395a06df51e014379bd99d209a58cfa3be56dcd0194cee9c9a68a720296fcb136c2505c59e60d1757a259886f407aa4c850bf0393cb6f20af210d8cb51e73faadec5b13c617a6ad84e24914b4d1f8b19d15f8c3278ea3de6c4d551be2c86109243238f7c7cd0f702905d3168994e3a89b3b6815bb81b1be263be0ca8c8ea53aafe770997de65b56076b7df5c09eba497707331bc5730ae4b8fb0fe2cc84faeba64c6537a61c69a20b6debabb398ef3a6733b111df5014ae8ea3f29f476f719228a989885fd13cb897ec9fe9e128f298242ee66676ccbcb6d02c577add2dfe6f06e861e2f6eb65379148d1d68145427a7be5bda309c59d08cca9a0c47da586d990a67697b416cc2ad409dbe8aaaa107692f9f096b8fc76fc67a45ee422e240bae3b179d8c0ce83d7ee843c92d44bb66dec64743e5c0e79ca524ee9f411806ae2aa6a97cf2b486ddc82ca4a753e531bf12e0a3bbf2ca3c386df181f982cf3eedd4f6e606f227b48e0c9c390f57191da3b89d39aeb91850bc6ebc8686ab11809418548ca1758ad1becab64adeb361743e589eaae0976f0a2e500c34207562db576ff90e9216584dcef786bd5ebc3f092857e8f17a4b24fcc96ebc254d83360980435f5059653207df3f43b6e15830a2b2c3edfceff85b72a72d1cf1b0c8250e0b415bfa5047ed08ec20468ffcec060c7128b0acfa475c7e70d226a5c673f3abbe2778b9f7433d6bced8097ce502ff2d03781f8ed6bb65649a0b740688682afd7cfca3c9a6c22947e3032807402694b3692028fbd161439741740c5db760cafa638bc6b43c078b42b4f14f98254f8245b86b4898db2940ea8118734e3a609684931bc7e498475352cfe021745a3c92f624e3ce64419e573293baf2cfa1318200b0a8cc1628c50a021922d3e9051bf3ae4d48ff6595474dc6403f6348b098c8ce71cc82fd46dd6dcd19ce4f78cad9bf223725eec4edb55c1f852f1aee7f18966329e675ed8e7c387eb4798004f778f8123e4e50a1534df676225292e4a248657b0f6cf7f5f38ecdbafe8b267947e156c2995531d1db07711f0aa8bed4f68a9117a3f32772710f8125ac673155da3e8e492970dfb9142087664b2d98502e19b54d81bfef5425bfaaf201ae9f9e1b46004f65b7f6d25f8c17f1c8dff13d4f3d083b24e37c5df177fb308b154aa300b302c9c39b92c5a00e1ce49fa562329f66a406d66b4fb8183fe41cd54548644a973371e4718a8d43b952c2b11a0a8872e272b78249d3b236e0b77e30290b203afd4b2ccdc6ffa5aeb66c8b97977f030a23bdc1ebe882b1d6caf07b0f8c0bee22f10834c854ff48f32068ae1ee18980f37f55e0f0d8e30dd8b55e0bf09780bf08f9f0077245c657945b7fa1d0f6981ff93e92449f8ac0f111ab4d0ce0960d3800284f67c8f36699156c67ac30e9abfad921f66ae90fb70915d575e50ec55c4540296445ba644d682ecb68a18803c8cffe93ec662cf20a5f3eff8ebb1fb0d4f97546b3c8dc48140a98e58bc2d132618e9606b2be1140434d2909b25a268a45eb85d847b7e2fa653ea9a9fa4ab5ddd2094e2edabc38f785047842727c737bb3a614df17d9da2e6a477fd602938cb9e7b7457232ccdd4f040920d35018ed3688c1d0ef1295ff7bfd02314411fe1685913803a10ef52f69bbec758428ffbf9424bb6f4bb25a05d533cc3d74e5faa09594e8ba20d4fba2be36a45f3180fd8f86f6c78417ad014bb248a0a69a2d83ec51c58c44b8ec3eeaa95fd80acff8fbee99dc8d9d8a0a0a2a60f3741b9512123638f18323dd4b07d3cad4c3d6c9391f82036782e52ea0a870fedc237b46f7438f3ca0def495c708aa17158679e8237b5028a89525885c242a566cd81864b368b0772e90c26e57463df4b13a7542ab339f9f0d2b67ca68b0a6357b6cc3c95ae63f52ec9a080a33e808e29a4b8ad5d5979857427f051186131af79d9ebfa7aa08b1ce964db46c63d1f840e3e6bae546d30fd4e4f3bd51429de4f8bb11cf8fd4d02964feb550bcdf21f13ba1b3fca3df14dcf701c378a7bca31c8530bfabf8a429f9c21849def75f9edf4b7387ca46e291ae224cb232c166bb60de8691a925039cad48e80de50e10d05ab5a74bfea916f5f91d1bb9900dbd37fb2f8663afa30eeb1fb89423c64f8ee0734e94a6a8a5874667ff602d4e2c9f1a8d10148cb7acf1babdfbf61d6a993918c40fae134d260849652ad6e1074b47a31901e4bd4f1579ae2cf0de9e22f0da76601dfa511c866caf9a50b80ebc1d410876f46131f8ecaf9b50246f46bd772b93479083dd7488d85211c8a8af27b32367c88c4c59e993f8772c6a7e84f965e3d675642ad8efa8e1c2bece1ad48321e19aa8a830cbd48e42012b0b8eb6008f217f6bbf50a9074d9da476e0bf54dd2fcc95f6df25da74c28d3bf499f6b69ab1e67acf025f79e17cffcb6c2f8dee308cd38e7068d37032777cfb9e66efb4aa788d297bfdb83a10bb69ef59043d80cb70b49e975b296ff3deda72eaceffe5e8850cd225b3ab313776da3e50de17c44510a528059700aafda6f40056e5dfa4c740f6ac95323d5c1f7775919b95b50a29ba3931d757060d2e9e3e1c6ae075c7d6d3194701c33cc294f11e6e01fb08bd313227c2a18267cfaca99c3e75a9fa3814988d70225b0bdab1bc635394b9e343579b02db021b5db3190210375e018e46c42125ca94dae6486d19ac0329ef237a2008620f698a51affe9789baca61fc574e2f4429799ab3bd37f994cd1897f07d43cef6d0023d6512effa2565bbc53d197a5b4eac6b7054934b9155b319bb9ac01f7dc618237c153e8673cf9696a86fb2bbb7744f7f5336e83de8dfba18b84fce7741b1bb4f819b6f25f43e234797da1ab503b767c692d723660e06de0306fb7635729f72548891df366e435866495781f2f923a279e3acf111a9e68397b2387f01298f1e3d3b95654c1b605cf02bc28aa5df3f6ed511f095914a58c4fe4f05afa10be9b6ae4af1e5b60f8cae7a5963d95ccc2e415dc8afaef9862b3071a48b4a985c8d6bfd9c2a55326325302888f0140fea792ae04fa78c1806015cdc5cdaf4d1b09cd59adffc76803f055324c69e03be7c14f59858f0f8a2a91596a85321e3b80d9d9d723bb2efde7940e519faea99c756175ca4b896e9c613fd70d8692c7abbac26e13745fe016e6245f6b4adcf2b1637095b18112be21da32f60708086ca96b57d2c746050d22f0584b514400b517a551670e381cba0877a9cb698f4265288e72452d02957dcaeee39e98782df07019082219960dbd796c782b755b258df696c2086c00aefaec2ae175b0a23f8755aa4bd3e7c0fc31ba5fb98db60e6c16a56946fde8dbb12836c8a9cb116f9456e06c82e98e0f9e05fb5dfc77adb7ed879f918b0104c316376ed67cd21e48dae3b1b21235f811ce42ac069f8cb5bd11457ec178a93ae320cbd3be7efa9aa0728f07e326b34f1c9de6282345d1694c90beb6627f9aa99f53d4347b2f2b6f6e8f6a6876c21c63002cba4f5d41efe7b24f8642d684e6b1eb5ac2031935b2286149290d8038d9c5ddbe33edcb2930a20f3e8934960f8b1c5bb253e78ec04239d88bac02c4a8e8f664470009a890cf382bbecc55b6589184aca5436076b2fa1fc1da4e9144cecfdebc0a6ce0868c3031e32cc9569f0d1b6996080881b47174af6fdaf624499e5463ea2fdb908e329746e7b3f51281fef1893baf133e72d440ea30507797ef3f1aea5592961ef1cd747469f5870e6b5ae65716ce3cbc961464d2e6e516a66b732d0dc5cbbc99cc990a0365ad756e822166fed9da9e5535fc16cf4cc33d674ce6e8ad66b55091e37b079111c5bee6b881031b63374f98570a2b5d7549854b3aa030749b4d991ea404ec172fccf2599d6bcc46695fa70d83f62bfaef1f5d0e4c1e1ae8ec7a2abe3c783e4b649672e4c761a26274d9fbf52c3a3ba882481952c4e249619275d6a1af7c974b259870280648f6d15661487add5c6cd8e0b1df994e5bc45cd33cb9f231ed5977f8c4fc10bcd3180bb98360030952060c049ca5886c5c738b5e31ba613a3ab7272ae80f9007e529f06c93f517a17354606f4238ce0601947164b7d337e6237ffb26005ffe7d43654ea06e84d990706a0e2bf016a23266b2212911992b018dfc01df966a617b4763fc3a27a60f50a2ef8a82e8b142924b78f04c52b411e186a5d3933d5c5e0788eee33738791e1cc6812b6f0afd93e6b3c6127769fd45506e4ad2f504543e860956dc7453923661a54f00e12262b06e78e1811bcc60b988112a3e4dc6e0b624843271691161e4a3742287d644d35da8dcd6d1574297e1ebc6fe05663de8a41a374ada54acf85eedb62285900b8b7144983ef59730b5d0370eda40ed5de6d2b99e14a7359469ddc07d028bf024a707bb78aa65259fb93d367a4db65496db2e73865a2dc8d0f2cb9d957aeab52aac56b6b07416fb91cf3cef1699e5c8bf29302bf7758ad31045a734de95365c3ae1d30c3473d4648940d95a150c16b2603db5441e03d58498e4447a2c23e39f63378889dbfbf9af8f02dc9a34520d90f0273395bb6100b66f2b3c3248235ff79bd633cfd43ae42a6e31c3b07a7a16111155530ec01553b64b7fc3db628119b69afac42275f520d3065dc37f96cccb2a9bd7052f093b1f885d793e4a9aa93f79171e2d6c2229525f6b1e5d395db24797706b69d9aca545183a5fc52b370bf2ec7c742035b5e3996d12a44824671725c1ef2a04172a3432962dc936d91a51c30d53b169c333a47e457b74e4dd88e8751ce91c41f5d858687b10a90ed080fa0671beba10f54d7a1a02509dcd6485b7d6974af0a6dfe2eac217641476c81f5e599a3f6423457bd76de8c8c09548d4587ac7b217aa541cac41c3fc63807a965c7f9fd5a9e6865c61820d7a2110f5d039048c43e4b9039f33dd73a075d96946fad161d85a25e41832988bfe9a1a448b16640085335761f093e08a0ebb4ebb7b9154f2bb1951222544f25efc86ce176eb6ed1fd882b19059678fe7a717bb3bf73e29b863abaca8ad4ac85ff8d1f7b811bfa696409e99a0a471fcdfee28ab22a6451fe21040cf89e70ee774439a53e1b572235cf316d2a81d3626817c08bd660a6ce8eb7d8a113016f7fc0c0df5bc50ec9c4ba97e36d31b28e8285974a674ce42c294643a4c97824a39bd6d7d8ea6cdd3512ff82e6f26691efbb0acb96cdafda5a6ec6ec10e5554d417710b387b52bac998a59e6e475180426ee1e871bf47bf884caca50051cf3589763588f7d8a657c37c89372b24b6dafb176728a0b40eca4b3addeb2d1d038c42bba72f72cf0ff04e0087786b1c09a7647ee24596d26af23cb4af7f0c82947f7bca7bd270dd129c9fb10f04a293c1ff6fd3e0546be94d7cd70d3b3cd391de37c0d34f2430f1dee6388faf4cc2b139b249d8383a94c73827213ab17977d1300928ae765ee80659b41cb9ec83ea6858a7e65a370de19f10113c8def4f1c5ede4e670dcb2bc61ac20e2ec9266e4adb95fe1ebc6d91338ee27fd28b512eafd892e073efce79514334793f8afe11f9cccafda5e7a4ba5576dd93d42f626d8a3253f06ff2ce6879ea5557534e52c4dbee4b4ee5ef0b6d30756dc6707d4832863b5b76e157236bc25613e4785b78b610ffa291f1181eb3ec25f6b838653c1524d549992ae8340999f196c34f017377fa13f4693aedefc31ed3ec9fea28016cf90412b738d0842fb1241652f648d7df56e7ce0580b324ef50011442927835bd4c104dfdcbdfbe5d22358c6418cc97c7016949e089f57a4a12b39081f09afa767b76753663ded867c1753d8308757cbf79832159dd08a8608fabf6ce4a528c4f8423abe0abea3e75fca7e6bd86546425b13b2591779e50ba54c5a44e931645e7111a6931be3f862bd1e27c3e993b034e5699395483d5aeb72c0fd23378f82cf70ad135da76fa4c9c9e974321c4ff4ce9c2329c54bf31bd0f8e95c52bc69cdb5144ea81961c80a8016c8a8add3b684a37f0802a94ed7a7b5bc4d8c515de3a6a791664c9947d1c80564bade57c4377c6164d9f9d5c97ae8e36500cb6ad4605a47ffce51df7a9f28a58d297ecfcfcb8a200dec80fe0711dbdc3a8f54fbec0fd0c8581963b65b2b592aa34f54e79dcc01dc091fd5e742385ee9a67b064887ea3ca39934eea879db361ed0e86285beecec9596f9ac524e9a72bc3145ef872823231130f379b655639eb98084fd5601af81c9029681e0ea2270fe20cb156df194663bd0a7a2bafbd6d7cd110c5ddb366d9f7d550fe41c2a8a6efcde39c9808488e41de47f98f9a848982f6fedef53336c7305416fa81ab4161634696be915f91f74b0075d8fd1cb919b44d4320b6d52aed18b33cc661066c899fe7b3570f5e80704fd113c5723c2d2e090e2a959fb6017779c42caab96a3a78273eddf2d854f2d2e291699770efa476983726fa4c0ce4df9f67e4c45b8cc050e7dba3c0bcd0ca7238a60b5c66cb0096895cce44e81d2493d80d70555006e77d97fa8198ad504694577ce77d5e45f4e5af723e6bff0876fef46269fb18245aae0150efa4c218efab599d2e9fa78ef6a3be105ae75d3d5183e8f692f3070c85625bacc2b3f660121e34686cc679ddfe2d34a0597af51fa5c1280616eed4d6a13da60ce6df365c35704afcf73b2af24b732803a9f829ed1458ad138ded91b337460fcd4bca1449778d8fceec171f01b9cf22750bd3f87b539f746fec8a149936ea8c44d49878cdc7011c9fa40f4706460b2335b70db83efa7edb019db961455b50030aa28c54e5dd268691feed709b88b9ea7306a5db4d26d85979ef2555fe92d190ffa2007f65e2ae832307fca978774d519e84bf678e6334cac61c826220dad5847e2db2fc6e47128c8075aadb0517ded470eb7cc54fdd02023d60a22bd43fe88d78b3583196dc576dbf002867e3e7a05e974829c907b117ba10b1821440ab32406978631aefe411946b460f8b6df97061914666e38469bd5014082b3cabbd41210442d575df9956b8a7549c057c545abe27b67fe5801cc04ae6f7df3282fed2cb0cf38aeaeeecd56337bcdb49acf2a11e7f17d47297a20667320073c28fd86542d1fc62b4537821fe61615ae82e671e47e9349a3aa2d59d6f59ec2db36512b2b4b4a91ba43b5065f866ec1241e8f327bf625837c95b7efe6f6ad1b36e124964a92ae4fc874b2435f95ad6f5c311faf4ad44edc45c0a4b830df23bd96a6f5745238f7e3f29d3cc4b27800ddcf75fb886fc0dff0544428daff40f9b603d64300b9cc2606baddb2c448041f386742ec020bcb4346493766a75ab1ab44ec3ab0620dfed283d28dee918a383aa9ffa702812fce00feff7c4b6ec43e155206cfef46c5ebc5642470ecc11205d419b41b1da6509ecaaee0436d9324cbc8e732e45068292f2c1189006b07989ca06ea24d0c1d4383ec70bc0e53af74608ecc54385350b478ea5564025abca100c897aa6ba6a49ed068e78eaeeb65b026fb2b906124ada78335ec8b175475befe4556243d881e1ce7cca3235d177e6859101c99d401562c00250893c6109d5132bbe0a6995d86a8db3fcdac139be01ee18a9ff444668835f795c1cda75427e6adcc2950b2639c61d0199a125428a0a89724b32751d53e5c9c67f2c78bed74f26fd64136ef7512f6a7ce2213e1794b38ce13bee55676d2793e64be69ffb6fd47afe58ba325db4d033c4ef6c5b9df9e48af99dec8b607e365a87ecefd6404b268ddc5c417b2de401d754f73d5c9976f62499c516edc5d8faf2e60866ce5d0a7151ca84c45f9da03cd46a1c0724993f9dc9cc419f8edcbf0f62bd05f53e660d3e0a485c0784ce6a9197ac0db365c60a2a39a4c850f313277f222c352f1d7d07fec5008d271d49a10bf8474a80b93a5538a01ecc1d5344dfe9d5eb409321e8adec51e01ab3a6fa51bac37827cedde403264a768d642c475d7819d24259a3b8e24440952227d00c64e0d90ebda0187405da414fd38fde3b609693a48f43f4884675ca97bd2e2b9fd976c34d87874dc91bf54cb9e00c4e1e89f014c5fd4c2b37ee430a64ac0673e5927134156a378aa0f8d99bdeb235bd24501577dfb4e5d368bd89d81e227938d4dad0b84a5c2f63981987149d8988e5543106a6a5b73e97ba25672595e05a7d9343cac9d9f03a26ee75465d1a6f029a4fc5d7bd698c754a0e4fb8ece77d79597ba3d1cd5cb33268fb1a5dbb923fd35ab234d6754674937ed0e61f17a43e1bdfdf644fc0a5bf4281577a1762391fc3e82dd22e71273bc64c65919a8401d591bd7f17835d0c5c1cd8b87d60cd05af4a2df2991c51ef3cffb170d72ab8a333690c7e5a46b246139ebcffbd693ad6cf8ebfd052b3d93fe2815d46ea20a92e7f4cf5282cb66f6a75782bb4c68aab5d0eaadede2cb19a3a51c7aa40bd59218c9818592a935cb9434271461b672287fe0737e975a8780c36d4adb44779b688a76fc5ab62b3702455eef3f67bb35950516c104a0228064632995101165c859a687c62529d6c36f0f35a3718b9f5c1fd055a5554b052944eae42d7f4a6ff6564af5622e56bce02c085fb2efb92541d6c9513e4607566819ca76b47f1035965cee416f5a254b76fe37393ebc48336fc474f0ef89d58e91c35afb2ce459e52f0f7be7dfb8e4adb45159fe5fbd469d78684eed54ae58db397118fe88dfaa8a492c7dcc3a5bec1ba1aa22ed668f9098d21161e34abb51c0f78d340fa579f16375e74991e8e5121e4d21965f7b5c54ae36940571d4e046b8a002f85c71b3ec8992e3867937cf014df0c5d1ad275adf6b599005c3d252db5867aa20a729a2ce9ecc89caa4e4546622a91a63a6b0f79815046d2e92dfe4df5fc1d4d71fdcbe70a56c277eebffa7e82404604c83747c5b30069c5a9f22a733b5eb8fbef2cd1b8787749beac7b2d5a04cf0f3aff9f805bc7b4df94d4d2c286291c1a9387ea56a07c6028bf73e57d5d7846067ce6b5b45d8e4d6b9d9b77019cdc7e0504603ed29b812c51028eaa571eb2af95800e93b1d053d4e6ee8aa0b0fff3b688008c1f95cb6bd13ae5fe7bd963df8da334e498096c969de8a6931fd03aca70f258cb48826a42428ef16eb72f23082f843e4d7cc7dc50ccb2f1448324b0235f6af22949c70d2e8699fe6e80e42ad96c2ca53d75a19be14fcb2ad09746b569683893d94234888dfc1e9c6298cf3cd19e0ee6b37f58dea00a09dd16986913f23a51800719e671143d249702ca52f0ec359ed5b857959f24a11e0c2d758ce1fafdba47c6a2bf9730c4ccf8b34c44ada0a3971e3072f45e353984b493072967381a4cc58a57520cfccc0c4252d7fcb18f08ab9ca8f618a0b13800ab90bf2df279ab08231867fdd67f8393ed3971d0a4ea8ff04225786c316d27c27b3b30b0e8409e020149dc5cc28f280838b4da86d95c4a3c94a66f5f5c5a0900c0697d4935a3510eb5e96e58f54afa0addaaaae9bdf81dde57f1c7ca46ea47eaf8d3cf2928e2690c94830f40146cf7f8e1725dc8a50c47baaaab7b4f955f7585d4baac443a00a9eaf2f6b359b1d7f4b0ab29f7c3cfa1828af9eba9c081b8813bc1d74626741c672fbffc37e65a1782f24922e0d1d3ece0e5af56153920ab4521ff15471007e0cdff41d4fa912878cfc4d548afe6c3e48b5f81b557f69f524d59f82755c21f4ba314565b5c1d86a8657490973a05f348fb6b83a4f89dd530690e1ab40433d7167aaabeb1d9ee479e271ee7ea7d6fa0cd71b010b80bacdfba7e00cb7afe1c3254fb37150a11c62bb6ae056107117b25f91a95f3376a22298eb0be2eaef884ae9e2d2dc2213c8d82f6a60536f479a37d7026853c16a9418931afa490f0ccdc630e6e38537ce4fbb49f5333a66f32afa549a1d9dc27ea6c0ecb781eaa0361105cc2faa75c8373f77c9f10cad4f27165ad3cc49b32670b4363affb443d1dcd23e39ed7f541895eb7a3450a28fa7ee70d40b82a9c94baf0a6bbed97d2b4673fc3e0b0ca2a1658ec371a0e151874d90265267199561206118685c0a6937072d8f7e69b0e5f557e52eb7d11c0edb88209c6840d4f4c9ac9351147b6ee2bdc32630f1cacc1a4512095fd95380619d485986d48a2517102650064a8c671d2381acd6e5273c3963138fae4fe2369dc11ff7b0443f7084bce8fb2b57d25a372bb7ab854707daf6a442ed27505f1141019811c8eff310eda38006be1b29cc7b85d265305cd9d2e3c893fabfc75aee23f0e9d17c9ecb86f2f8b4c59ed08d39b2eb43d32e826e1c13607d25999aa59f555ea3f488b9b5752b2c35725ae5acc098c9944a09a8127001b5a76dc69e07a476459b1ebb11204b9e320e09ab1a6b821665c89dd4ff45a42c3c74dee4b68345f12c4b778c7da753dde391456a458e52a59b70d9376230a5b486843a4a63381141df593f8985aaa42c398fd769d8986ee444d9b022d57c0ab037497ef770afe7a74f50b7fefc5064f22bf953f0913439fc28f562e08fb35c23ea7182f245944bbf26ba419cfc3a4f7161bfe42b8fb48834c01d1121af7bf4394d2b16da3d4d291e22d44c7cb30d5e265ec6b0b29fed72e8dd2705f8cab585685d0086cdf810b4162ddc7563f6278394e8ab331556a396ff51346bf65b5f7704994f824fbb821add9b202a5d1ecd3b54ba096f4fb78ba27892dacc14b6bd22fc85127aaa9f0877a3757f54c2175b6a0f9d3ad94b330d2d045d73cd632108c699b4e1cab91a159b0aafac7e66750f8625688153644f7a78ed3a38626fccd45838818936a5d912bced6b03b67b2cf4d695f81e9fc1304b4166d7ad6d93eb73e83ec9ea0cb0bd5a60e54db4dde4d2c644c2649435fc6fab08aeb3df1908bcdd700001793bb39cf11f5f75dec31787b95aa24ef3a4c3ceabc9b5cfab96b74b56655f92b36ae4aec778c22a15ec444c8edb6d737acb3c2bc6b262b845f008646dc426743a9943dcb2520b1f95e2358dd519df42335d0563b0e22ffeaf579c4908fd053a2b863b116e2feb897d5060a41b59dc78e2b3d390d40102d76011bdbdebe6e8d854b7fd672cb8adbaac604ff1e069c3494376f5a2be3fb715fadc034a5b658543e179da0da398eb41d01e57f653c79152154e8fbde9c8eaf1eacaf06f6b3d7de939cdc03022465712576c6e3a3dc4bbe1878bc6e25d8c7ee6114a4e5b1c533e94a442286a20db34c99d16e487f3745af97dc638d99afe846c813ae083b431b538af8a85ae5bff1f9d0e1cf2fd89cbeffaa2781ff2990f0ec962cb13ea7dc387700311c05f4c912705fd47be96ab2a4ffc1386127cdabf525ada8264f15a32656c8fea3936680c7aa85c8ad4314d17f2844cdd7fd41a5825c34866944ab2884fcd258794f503536912053957de549019121cbf705d5d81dc0a9ddaf9842ec3e16884f90b23c08372054fdf009d2d55624eae05f9a14855f967757edd65b5e9052e517b7d8b8953b8a28b42c7d7139814ff0d2ced7390d47503404c1655a7ab447cdbd99348e982c517a848df6b38c86254df97c5faca7630dde10213f3b8567f9f9bae7a3c3342d37410fd570c3210f53ace30bdf6fb204ea0c105c31d8e1835d61fb6d016370292ff4d8db6307fe2da597df1128fce43c93b95255d061643b2566a9e586020e8f8e7a37830326b2ec185f51764c89930639c06594604d4d5adbdee0afe76c860991b379d2422de4854243cd4c0dfa629874be221726a2eae817382b5c26caaad055265007016fbc460f4f0f9d17a1aa895a12ee53cf8a137bdad0a8937d30f5200192fdfdf0b8fb789c4242378880a55425fcd033656573842ba4316b9b19aa2d68ddd2e4833acf03c6f913e8fe16b466fab9c107768bbd864e5ed43c91c2adc918189f36548c8ab325608153a6a395ed1cbf43c9593c9e0c66b84a06b4a886c4a38d9f8aa6b4ee48d80fd35e8b51983f7ae87ba72d8083302da8890920b947fdf9b0846005b48dc4463dfa9b81eb0c9ea7f2fbe4bb31e62700b3100d4f47572edad60e5a42e6119481c0ed00ba1bdfcd657b5ac3d4af7f58b5ab90dd50342d24a1f761c5f2336ec5a9fdf2148776ccadf637cfc839bea60f8d6e71ff5082a39791b742b1a3fb7ce9d6cbc3675a9fa22a114220b3ebe4a24ba12ea438081d74ad05063f6278f48ceea3b968065274c96bcbdf564f8972559cb574d033114b652780c2e17dbf69cce73516bfe63d94fae63330e339bdef742e12f2633697b4eea3aaa10f5320ea3a9586ea5df264309421cb23bae036d1a09912d89b1b4018ba7bc17dad6791fbd2477401498803dcc7aefb9d1488502b4c99e3d64227f931568f204f0bd189283d65f857b202a2949c0413d33ad8bb246047a7d5baf19c40532952d379e981697b847912818fd15b50a4d94e1e56eef7d0ccc165a93dfb96aee61a1c416950a7b8b4efbe4a43fd2ad9d949ee168cfe1574be9caf37c52dce796eb80a2ef0c4bea8dc1baf9b2cd68a7f8ba5630af72d5e721083deef6dd04ce6bf3d5b2f6fb79ed731bf7bb84d46c8ea4641286f955b0eb596506e521d2f8ea5d5667e901793ab99f2fd0860bcf91c77621755eeee60593dbf35db6734e9226ffb15921ada132543760e27bd7ff2843482d125032aa64568ec9dfbab2c95e4a8bc3a095c35826a2ece32e143ab5067ab05685efdf1d0405c124b4a9d2cf700f2f4107691aaf03dee1eaaa082d69d72f055201a1ec7b9fe234fcbd873e6308f18cebc8e5ab146ca401532e19753b85c3a1ff9b74190c1863157b7065330e8d6a9275049338411681d413d01a2bf07d55032ab3c915ae94a202a743f305caa582da8b2568d9f4b1379c10a8589a48df21e5f69bb0dc7b71606b126ab57a5f0180889d3f516db883b1347213680584fc4ed2a919365552308901029f105f3f6e008b68c174864bf950f0018816966822252c3837912af16b108d7dd7d7d516024cc75178695e63572d0769f8f98881ace4b67c3056e2a3f0954a0f6727bb01cdcf24a23f4629900af95744cfe948c0a2f331daab4fa138a59ea44b81df50049e4a1dd5c3dfb13c350bdda8bc3cd9b2c9a69166d0c21acf75f328656b09c11403380aff4a569410f21b53bacbc293d4587a4a1a24493fbffabcd2ee1a33c54e5976f5bb2eb0c6a38deb5310effc9a154c9cc97bd7a0ff6ace4f180b886ae42cdc62a24e1265e9cdda2efdeab8e4ff9783a25f69716b30c3a2696fe0a15aae5a265cfdbac9c2eef7995fab73dd11084a504bfad1014eab65e3cf202fb200929bb1fcad3231b92632c66d2a370dab20b754a846abee0797d9c6971a4cfe58f8e030b962ba1cde4b0b9c822cedf33180837a66065991700d711d14b2c1ed17e28f27ea0f99d2227f9b653253c5a46f23fa69cd6c31c74fb579f8871accc09b71703ff354f90d8bf9f3a5b0e852f870ebd3c97b464af079ef802b9cfcb1cfce66f0f62f751a7ae9366c9a0b6a5dfa1d7d3ffba425b21dc233cecd8cd826438fd1546bd3691e5d04b7403caca4a8c1f7d08f0f20ed511f2abff2501cb3487dc35b8bc8f2ba9f92d38748eac1f6b21d70c0a324711fcae311e64d3db8e7eecb6fd25c16c9662a775c5bd7dd1743645fdd5f0e02e950ff5a4563266e51d90e5e75b1e9a9e92f57f1fbdd6e6ce501f32d4a133f3b9b0a4051814ffdfb454edd26e34e3a98612c586a39dc30f059e2ed5d8656fd79119ae5ef6e169287211ae390d7449fedd7244c017d2056c1d49c0f3c9b4249cca6c636c5201dd56f77902129363e1f4c6b06a529561b1bf83cf5dbc388c8e97a868d74b996524be7b420b9ed54c9f80fd4f4c79f63652ce2510cf8996c8b18c81745dc8c85454701cf63893bb75dd47299cb2dd9a9384376dc1e7a1ae5b36ee439eb40b37d6f859ab4c01fc68f4c66fb73fc21824d7943bb5fabb775ca6ee2566af692e3ef14236815fc9b4b01feee34a5ef5d4bfa9723c980ac3bda6f5b3da470cca36aeee53cf98d3dc0afe7fa3687c5eaa24b85edf367c4b88f35f7035d6ca40b661142e33b502529357ecdb8d6ffe75dfbc3b109ebfc3cac5ed2ce7045715f53af4a4ffb6d8ae3f92ad0749eb41fdacbfe91a5b4fd761190adbbcbc4fff66f01f566ab343bfd5a95331a5ea6fd3466d9036af0eb7af3517a36e5ef7e4d286529b0be10e8c06783ae0e06717a0b910a00f12a25eb254b5eddc92e48edde4e3e8dadd1c961629ff21211c76ef0bae5ea977635f4313d7516a8ade7b59629479bb4caaf8b4d3d6d7d126728da4ea87071f4bb2a68b34cdf2b5e52825192d13c59928157f43785ccbc4f873ac1fd28d311dfc1b6f79056101b27bdfcf4239ed85d9991abf4a6c87922282a6df70f2037b4ec239eecd7b0b39a15d02afdf91b1d7110c02a5785e667b1e9005f10a65e15f4bb4b8c7c08c18e21707109feeb0f0ea9ac611eb515fa5ced82866119801fa093e5ef1bd9e0089755bc68e66e87f54b0a9d857a9f0baf37af17abadb26069834f541c0f5cf1ed336e05bb512adb21570dd133350849d2fc461b1d63cc2a14787a1d683d5d9f47a0015d0678ca64a68cb1f702d75687141504d7b5ab30e6484b94279bbaec3cee89ff199f568c226fc1e84bb000a3738f49b282fc27596387bdfd82c662f95ae157d962018ef4d2b543ed6828f7a88ecdf1ba76b30add2a8c8d45654a46cfbd42eb4fc86ba6a28e61e1c692cb2be714451832a39f566d1c29bcc208aa5aac5b4a3e64ad3e14dfdebc78560fea58595aab8655efe8cd5ef31cb00b1ca47baf76cb1762b7e1c0512383f5952f5f3c555411ca0f7950acdee102de75fe37072205d801540de12a5ff54ad65a6367588109819d8b40115fa1835c385c3a01804c29868b2204a27f6bff6481c001870b0be58da4c9b23a1b6bcf06beefbc22824de7c4e450f588fb2c2796f0c19f94a4d5994c0eb1ee09964929b81a301a95819c613dc042900f2c14fa270c5bd04ec56c32f68087aaeeba667194112a624d136b998a5f7581c8bc198e0654db2543c135233ff6c0f7c646971cea049c7f353452fa9354d14d3102dcb63f2193a86b7a4502fc3a64213c3a4160ff22a78e7654510254114a2757f42a452c151dbe216a74190f2b0d7cdd8789bf7bd7fb48cbc848fe6d231f066ed32b9470816b7dc2ec8352c5b4661e0e9ad95084fc4f06c94e8b5a94ed0ff23de3ced21b77736ba5fd90230f9df278614476f2c5c0c5846a74523cbbdbdf1ff5be266c563e70b442100352240286a6a1469a554db1467ed124b0b90ab652ea19d61209c4ceff2b138c628024cc91e056d11a74cdd956e099d6d6445b4781d7387d83e945b245bc42a46bc40639237708e3893b2ef4ee296c24ae5777937f41ad573a9200fafc8c86e3c445ea9bb17cc0bd3e813ff40108c0d71296e8ed863f85a7355c98c7226d52fa9c9900ccc50f3fdfff927f2b7695b4fdf16d487fd9de6877c95aa9fe5384cb488f828d88ae794b12a5973e2596cac2a2a5a65d6f5b37ff51693d38481615539815ccb3223a775b62884c046a890b4a928e0a0e73e803a7ac709231f2aaa67bbaa652f2be1cb177bbe6c570eef25a8bd4876ace132fcfaee62b3b328b8816feb20e93bfc9fe1f43187a512a4dd29505875ec85e2255a9fb8ff97ccedac7e3bc203898cbf9b7c8688b30d20d583dbcd3ace426f56aead5dbbd81c3a46891f1ed0a339fe9241d815ba4b0feb3608b92fe43152e96ab136bc6ca")
  val icmpPayload = hexToBytes("080065cb00010001e9261a6700000000c2d10d0000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637")
  val icmpRef = hexToBytes("b42e9993bf889a45468f672e080045000054ee9200004001a5ffc0a8b2a5c0a8b220000045130004007075095b67000000001e350d0000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637")
  val udpRef2 = hexToBytes("b42e9993bf889a45468f672e0800450005c4aca640003f11a36bc0a8b2a5c0a8b2208600145105b032bd00000799000e0b430000012290e5f9bb434b067a6b749db05e445d59b173d713ea7de09ef7359152973d94c6b297631554465e6adc290ccdcb60b57d1beb4e5ce1d2ddca3de3dd87187b779457fa8cae7a249429605903f30fd9d2935b491c042f764b0bc3c0c7992e984a7368e547952fdb167ee471dd5181eb2a9edd896c1581c9c17fefcf2a42b3b524abf1748dad8605d71507c35f201f65452b08e2d2cba75c9b79052365047a1b0255c03f7bc07cccfaaa5b7c446f9749c7251271cfed78d0c16e67fc4c5277813e7d5ddd5702708c9c8fbaa8212290d9977c5b451d8688c15a159fd40d62333b41b731d7aa6a94ad0cf57237dee3dfb759df16b598192e14ce0d669f0cf44d891fd507c25b4c8cdfb17f0b6270b122def8696cf1fe719e752965be7812383439d85e27b799c21faa34a1f480ba87a131836bb6dd3c5b08d9354aea4fb89284953c9f844c5471e2620e026935233090c249052686f34be565b94c3b3bd34f39a165b872e112270485372ed06d57385b5624a22b0e0d04e06cf63779a8518d6a6bccfafc48b0d486519411d25661356a92ad978889dacbf84165940b3e24ae843582be66905796a5e3692712599e236036e42bc7caf46925200fe40c7fc4a97518bede6c11544e21a985a8c1c9dff7c591b0a27b3e3c99ca0d407dbe9b6ca5d120b8351b72ca2fe1f7e24f01be047e19eef8ab629708d9113ee4e0672dcc0f37a8d294f596cd52676b879bec316a7c1e8e3306733a9dce55a18f5409ad48f0ecdb44b11407932e943027b6caef6216f2298c6b1f3e3b3aa0df2a5a5e41cad721c6c28d088b250d18c1d4454ef7a68018592048b60e7870b89de08a0fe8d49be0f136fa4575eee6547679e31e2ce16cf4a41346ac980cb52d3733e62977438e047b04b498b292976bd9ced8c951f959042f9c7fd1fef98af8e2ed743825b2e179685358d923d83d65949d5a02e0cc4dd1d3b970e0f6ad8caa3f1ff30d80f37121fb3c9c7fa70ed61c56402bc128a9006d6fb36a3db5d01765e38dab11e9b2f40ce54ec2c7d6710d71ad6dd68f7586258ae3dcc0c31cfee19fbad1fb7144e9e5c1b599eb97a304ac67f2c43d2b2241de4b361cecbbae9a3b8ca7d775dc7b59eabb8aa06b389af7e67bff857e5eaf58847ccd91cecc7185f3909b042bdd904e6578fd76bb9582426bb0633389c8d59f9ce0179fb77304ae92bc1156463eaabc3a7683e23a4e8af2313459ebcb5822f5920c87d0d27571995bc45d926ae94c5b04cc84b46a5f40a0da21391afdbe521309ee3ab22895f3054ec445d48a7e2de83244ae3a5d50550238eb8e5875d25d08126c2609b405d54969019dcd3a354e703506925c69fcb09e93e311bc87fcf4506ace986b6ed98d7e307d8f35173838557dcd1b49165bda30db0d1b0af905c88f646663cc724384e42f57eb95929440e3e72c675820238cac044ca1ca268af3f12a123a4165cdde75c34f9a30854af67ab6619c371eff75f01bdde3a34bdbbaf9e44f6838dc06b33cd14a0d17cef9ea58e2bbb1dce51df4b61c3edb0b195eb28a2c933e1b14a7cc4bf92234173760d9f87eff513d0896c20f6c555f17ea9933ffee1794889e791c55c598fc5ef0a4a2324b9728b20b7a33c788108901097464d615f8c222e67306e09c6069268deae95f21a2c94becb34160755a9117d78eeb399a8ebda6d2dd1ca3fac3e74e3937478a8f89fcf74a0cafea2fbf462b1d988219cd14aa7c17243c14701c1eac7447124c19a576e7c889d973d375c93e7081eaf08d52344bc3accca122826668b1c5739ac0eb26c8d85175ff5c6f1c22b12f163b39e9773bc632a869028394a4962966d1cdb02dc3a7f227f1c33d2376babf6d019b5ea57f64438d00320e7125a1492071e5b2583adfca7d939983480b91a782093902060de88e3711fcd330c6f3a02afa3599724a4531886d1018169762269014577a47c4186a5db3d6207cde46959b5ef85bf449bb14f1ee908d69fa89a670cddfefb98bbf5ca630a9b4df742dd8bf17be")
  val udpRef = Array(
    0xb4, 0x2e, 0x99, 0x93, 0xbf, 0x88, 0x6e, 0xa4, 0xf2, 0xcb, 0xaa, 0xa6, 0x08, 0x00, 0x45, 0x00,
    0x05, 0xc4, 0x72, 0x4e, 0x40, 0x00, 0x40, 0x11, 0x3e, 0xc1, 0xc0, 0xa8, 0x01, 0x65, 0xc0, 0xa8,
    0x01, 0x64, 0x14, 0x51, 0x88, 0xcf, 0x05, 0xb0, 0x42, 0xc7, 0x00, 0x00, 0x46, 0x66, 0x00, 0x0e,
    0x69, 0x3a, 0x00, 0x00, 0x01, 0x74, 0x07, 0x77, 0xa8, 0x7c, 0x84, 0x5a, 0xe5, 0xe3, 0xa7, 0x97,
    0xdb, 0x97, 0xe5, 0x72, 0x22, 0x0d, 0x0c, 0x10, 0x42, 0x3a, 0xbe, 0x27, 0xe7, 0xef, 0xc0, 0x26,
    0x49, 0x40, 0x77, 0x45, 0x9b, 0x21, 0x91, 0x71, 0x07, 0x51, 0x9a, 0xa1, 0x2a, 0x65, 0x99, 0xc5,
    0xf7, 0x8b, 0x22, 0x50, 0xa4, 0xdb, 0x47, 0x0f, 0xfc, 0x74, 0xc0, 0xc6, 0x94, 0x4e, 0x92, 0xeb,
    0x8c, 0x98, 0x11, 0xcd, 0x0c, 0xb4, 0x23, 0x5c, 0xdf, 0x3d, 0xc7, 0xfc, 0xef, 0xe3, 0xb6, 0x8e,
    0x91, 0x1a, 0x57, 0x0e, 0xa5, 0xfe, 0x0d, 0xc2, 0xc6, 0x66, 0xae, 0xfa, 0xe9, 0x04, 0x13, 0x45,
    0x32, 0x2d, 0x88, 0x4e, 0xe0, 0x6c, 0x7b, 0x4b, 0xd4, 0xd3, 0x5b, 0x36, 0x57, 0x12, 0xec, 0x65,
    0x67, 0xaa, 0xcf, 0xe7, 0x77, 0xdf, 0xf8, 0xfa, 0xce, 0x88, 0x70, 0x0f, 0x5b, 0xe3, 0x8c, 0xd2,
    0xd4, 0x09, 0xbd, 0xff, 0xba, 0xb0, 0x59, 0x4c, 0xd0, 0x71, 0x66, 0x5f, 0x5e, 0xf9, 0x64, 0x30,
    0x4c, 0x84, 0x53, 0xdb, 0x01, 0xee, 0x5e, 0x89, 0xb0, 0x26, 0xe8, 0x84, 0x4a, 0x7b, 0x93, 0xb3,
    0xeb, 0xd6, 0x4b, 0xad, 0xa3, 0xa9, 0xec, 0x0b, 0xda, 0x5c, 0x60, 0xb1, 0x93, 0x11, 0x87, 0xe8,
    0xe1, 0xcc, 0x60, 0xd4, 0xbd, 0x22, 0x50, 0xc1, 0xe6, 0x79, 0x9b, 0xcd, 0x65, 0xee, 0xed, 0x6b,
    0x75, 0xc6, 0xf5, 0x2d, 0xa6, 0x66, 0x0e, 0x5f, 0x69, 0x13, 0xa5, 0xd7, 0xe0, 0xf6, 0xb9, 0xef,
    0xdf, 0x16, 0x8b, 0xe1, 0xb4, 0x3d, 0x52, 0xd9, 0x2d, 0x12, 0x04, 0x1b, 0x67, 0xae, 0xce, 0x49,
    0xc3, 0x95, 0x26, 0x71, 0xef, 0x21, 0x03, 0xce, 0x1e, 0x41, 0xb7, 0x93, 0x66, 0xc0, 0x47, 0x58,
    0xa3, 0xd6, 0x82, 0x10, 0xa9, 0xad, 0x64, 0xd6, 0xec, 0xbd, 0xeb, 0xbe, 0xe7, 0xb9, 0x44, 0x63,
    0xd6, 0x8f, 0x92, 0xcc, 0xcd, 0x73, 0xf4, 0x22, 0xe7, 0x73, 0x2a, 0xdc, 0x7c, 0x22, 0x8f, 0x14,
    0x03, 0x04, 0x82, 0xd7, 0xcc, 0x48, 0xb5, 0xb7, 0x3d, 0xb4, 0xc0, 0xcb, 0xed, 0xfb, 0x96, 0x69,
    0x63, 0x1d, 0x3b, 0x42, 0x84, 0x7f, 0x0f, 0x8b, 0x2f, 0x26, 0x7d, 0x51, 0x84, 0x99, 0xd6, 0x18,
    0x7e, 0x24, 0x37, 0xa5, 0xfe, 0x10, 0xa1, 0x2c, 0x88, 0xc6, 0xc4, 0x03, 0xed, 0x2f, 0xfe, 0xae,
    0xe2, 0x87, 0xa5, 0x89, 0x64, 0x70, 0x20, 0xbf, 0x25, 0xa1, 0x97, 0xdc, 0xb7, 0x09, 0xf9, 0xa7,
    0xcd, 0x60, 0xf3, 0xb3, 0xac, 0x2c, 0x8d, 0xeb, 0xb9, 0xdc, 0x90, 0x48, 0x95, 0x12, 0x06, 0x00,
    0x2b, 0x67, 0x12, 0xbb, 0xaf, 0x81, 0x51, 0x3f, 0xd8, 0xb3, 0x5e, 0xc6, 0xa8, 0x05, 0x17, 0x4c,
    0x9b, 0x8b, 0xc0, 0x97, 0x47, 0xdc, 0x4e, 0xaa, 0x7a, 0x83, 0x38, 0x73, 0xf5, 0x9b, 0x12, 0x0b,
    0xdd, 0x4d, 0x0b, 0xc8, 0xc1, 0xab, 0x58, 0x53, 0x81, 0x06, 0xb0, 0x5b, 0x79, 0x17, 0x88, 0x88,
    0xcd, 0x19, 0x15, 0xd4, 0x42, 0x5e, 0x2e, 0xb6, 0xdf, 0x21, 0x84, 0x53, 0xa2, 0xb6, 0xc2, 0xd4,
    0x1b, 0x30, 0x61, 0xbd, 0xcb, 0xf2, 0x7a, 0x7c, 0xf5, 0x24, 0xde, 0x0f, 0x18, 0x9f, 0xf2, 0x6a,
    0x45, 0xe0, 0x07, 0xe7, 0x9f, 0x99, 0x27, 0x1c, 0x9c, 0x1f, 0x30, 0x5d, 0xbb, 0xb8, 0x7c, 0x93,
    0xea, 0x47, 0x71, 0xb1, 0x3b, 0x62, 0xfb, 0x0e, 0x51, 0xb6, 0xcd, 0x8d, 0x3e, 0x88, 0x22, 0x3f,
    0x94, 0x06, 0x49, 0x9a, 0x44, 0x00, 0x1c, 0x93, 0xd0, 0xf4, 0x2c, 0x62, 0x74, 0xba, 0x2d, 0x31,
    0xe9, 0xc1, 0xdb, 0x73, 0x24, 0xf0, 0xb4, 0x27, 0x32, 0x31, 0xc7, 0xb7, 0x2f, 0xc4, 0x6f, 0x23,
    0x26, 0x75, 0x35, 0xda, 0x30, 0xa7, 0x40, 0x37, 0x02, 0x41, 0x51, 0xd4, 0xea, 0xb3, 0xf8, 0x1a,
    0x48, 0x05, 0xaa, 0x56, 0x52, 0xb0, 0xff, 0x89, 0x0c, 0x32, 0x16, 0x61, 0x21, 0xd1, 0xd7, 0x9e,
    0x33, 0x85, 0xe1, 0xda, 0xba, 0xc0, 0x8a, 0x24, 0x66, 0xb6, 0xb3, 0x01, 0x58, 0x77, 0x23, 0xb3,
    0xa0, 0x5c, 0xf6, 0x67, 0xda, 0xda, 0xe6, 0xce, 0x44, 0xc6, 0x1e, 0x1b, 0x9e, 0xa6, 0x71, 0xdc,
    0xe3, 0x8b, 0x8d, 0x79, 0x58, 0xc8, 0x3c, 0xd3, 0x48, 0x84, 0xde, 0x41, 0xfc, 0xfa, 0xeb, 0xd5,
    0x65, 0x54, 0xd5, 0xe2, 0x3d, 0xca, 0x14, 0x34, 0x97, 0x19, 0xd9, 0x00, 0xb1, 0x75, 0xd8, 0xc9,
    0x9a, 0xde, 0x07, 0xfd, 0x38, 0x10, 0x40, 0x59, 0xa8, 0xdd, 0xa0, 0xc6, 0xd1, 0xa5, 0x82, 0x7f,
    0x33, 0xf2, 0xf9, 0xdc, 0xbd, 0x85, 0x65, 0xeb, 0x6a, 0xa3, 0x46, 0x6f, 0x23, 0x3b, 0x7e, 0x4f,
    0x0e, 0x98, 0xdf, 0x84, 0xf8, 0x65, 0x2b, 0xcf, 0x77, 0xe5, 0x53, 0x9a, 0xa3, 0x1e, 0xbf, 0xe8,
    0x82, 0xbf, 0xf8, 0xcb, 0xf0, 0xa3, 0x75, 0x75, 0x54, 0x6f, 0x5f, 0xd9, 0x10, 0x96, 0x41, 0xdd,
    0x57, 0xdb, 0x83, 0x6a, 0xb0, 0x79, 0xe9, 0x63, 0xa1, 0x68, 0x86, 0x7d, 0xd4, 0xfd, 0xfe, 0x4b,
    0x1b, 0xf9, 0xc1, 0xba, 0x68, 0xcb, 0xdd, 0xaa, 0x7c, 0x11, 0x92, 0x07, 0x22, 0xb7, 0x7c, 0xb7,
    0xb2, 0xfa, 0x0e, 0x4e, 0x19, 0xdd, 0xeb, 0xbf, 0x0d, 0x1a, 0x4f, 0x50, 0x47, 0xf9, 0x2d, 0x7d,
    0xe8, 0x27, 0xa1, 0x3d, 0x38, 0x3c, 0xeb, 0xfc, 0x8d, 0xdc, 0x33, 0xd4, 0x56, 0xff, 0x08, 0xfd,
    0x24, 0xd8, 0x31, 0x33, 0x66, 0x06, 0x58, 0xd3, 0xcb, 0xb5, 0x55, 0x6f, 0xa2, 0x9d, 0xc1, 0x07,
    0x9d, 0x80, 0x6f, 0x1c, 0xe4, 0xec, 0xd4, 0xd6, 0xd8, 0xc5, 0xd9, 0xd2, 0xc7, 0x01, 0x55, 0xe2,
    0xcf, 0xff, 0x6b, 0xc8, 0x39, 0xb1, 0xa3, 0x48, 0x42, 0xf0, 0x18, 0xc1, 0x40, 0xa1, 0x73, 0x8e,
    0x2b, 0x30, 0xe2, 0x9b, 0xb9, 0x42, 0x4e, 0x3e, 0xd8, 0x17, 0xe5, 0xb1, 0x7c, 0x4f, 0xd4, 0x97,
    0xa5, 0xaa, 0x0b, 0x6e, 0x55, 0xe0, 0xb0, 0xb7, 0x17, 0x3f, 0x81, 0x3c, 0xe5, 0xe4, 0x83, 0x28,
    0x84, 0x90, 0xe9, 0x35, 0xee, 0x37, 0x2c, 0x2c, 0xd7, 0x08, 0x24, 0xdb, 0x38, 0x90, 0x7c, 0x7a,
    0xaa, 0xd6, 0xc0, 0x5d, 0x8d, 0x4d, 0x0e, 0x93, 0xbe, 0xf9, 0x89, 0xb9, 0xd5, 0x9f, 0x6e, 0x09,
    0x92, 0x1b, 0x5d, 0x18, 0xe7, 0x86, 0x15, 0x4b, 0xfd, 0xea, 0x9a, 0x41, 0x32, 0xf6, 0x36, 0xb4,
    0x18, 0x6a, 0x04, 0x1c, 0x4b, 0xb2, 0x4b, 0x4e, 0xba, 0x62, 0xfc, 0xbf, 0x30, 0x74, 0x8e, 0x9c,
    0xc8, 0xa3, 0xff, 0x17, 0xb3, 0xe0, 0x73, 0xc6, 0x19, 0xb6, 0xc9, 0x08, 0xe6, 0xd9, 0x10, 0x15,
    0x2d, 0x19, 0x9a, 0x00, 0x87, 0x12, 0xe1, 0x9a, 0x5c, 0xd3, 0x34, 0xb7, 0x80, 0x00, 0x32, 0x26,
    0x42, 0xc2, 0x7e, 0x3f, 0x98, 0x99, 0xb3, 0x1e, 0x3d, 0xfc, 0xc1, 0xa3, 0x76, 0x03, 0x4f, 0x73,
    0xf9, 0x75, 0x01, 0x8b, 0xa3, 0xc4, 0x0b, 0xe6, 0xff, 0x5f, 0x70, 0x88, 0x94, 0x52, 0xb4, 0x53,
    0x41, 0xca, 0x07, 0x42, 0x7a, 0xf1, 0x9a, 0x71, 0x2d, 0x17, 0x63, 0x5e, 0xbb, 0x25, 0x59, 0x01,
    0x7b, 0xf4, 0xf1, 0x80, 0xbc, 0x87, 0x0f, 0x86, 0x10, 0x89, 0x8b, 0xe6, 0xd4, 0x6c, 0x58, 0xd5,
    0x7c, 0xa7, 0x6d, 0x08, 0xaf, 0xaa, 0xd7, 0x31, 0xbe, 0x79, 0xff, 0xe3, 0x16, 0x35, 0x48, 0xa5,
    0xca, 0xd4, 0x36, 0xa7, 0x60, 0x1f, 0x1f, 0x74, 0x8a, 0x27, 0xb0, 0xc6, 0x1f, 0xa0, 0x09, 0xdd,
    0xbd, 0x6b, 0x0f, 0x70, 0x29, 0xad, 0xaf, 0xd8, 0xa5, 0x53, 0xde, 0x77, 0x24, 0x50, 0x08, 0x7d,
    0x84, 0x95, 0xee, 0x8a, 0x0e, 0x04, 0xa8, 0xb1, 0x5a, 0x8d, 0xd9, 0x08, 0x85, 0x84, 0xa6, 0x59,
    0x5a, 0x2b, 0xc7, 0x4c, 0xfe, 0x19, 0xfb, 0x8d, 0xa5, 0x29, 0xf9, 0xc9, 0x58, 0xa4, 0xf7, 0x8a,
    0x57, 0x99, 0x00, 0xef, 0x73, 0xfe, 0x84, 0xe6, 0x6a, 0x4d, 0x12, 0x28, 0x77, 0x05, 0xc2, 0x6d,
    0xa0, 0xf8, 0x51, 0x0c, 0x30, 0x78, 0xa5, 0x85, 0xac, 0xa6, 0x44, 0xa3, 0x91, 0x88, 0x37, 0x59,
    0x74, 0x57, 0x45, 0x13, 0x27, 0xb1, 0x37, 0xdc, 0x39, 0x76, 0xdf, 0x52, 0xf4, 0x27, 0xab, 0x7b,
    0x9a, 0x16, 0x75, 0xc4, 0x32, 0xc8, 0xce, 0x68, 0x38, 0xd9, 0x9e, 0xb9, 0x5f, 0xd2, 0xb2, 0x97,
    0x71, 0x65, 0x64, 0x1b, 0x14, 0xd3, 0x3e, 0x33, 0x2a, 0xd8, 0xd9, 0xec, 0x20, 0xdb, 0xf4, 0xbd,
    0x55, 0xf5, 0xe5, 0xae, 0xa3, 0x5b, 0xee, 0x68, 0xa9, 0x84, 0x45, 0x33, 0x6b, 0x35, 0xf5, 0x38,
    0xb3, 0x24, 0x27, 0xb7, 0x35, 0xfc, 0x1d, 0x68, 0x56, 0xde, 0xcb, 0xc8, 0x41, 0x23, 0xdc, 0x9d,
    0xc0, 0xda, 0x80, 0x0a, 0x1f, 0xf8, 0x25, 0xe3, 0x24, 0xc7, 0x1f, 0x69, 0xea, 0xf4, 0xf8, 0xee,
    0x9b, 0xe5, 0x86, 0xb0, 0x2e, 0xdc, 0x8c, 0x91, 0x03, 0x1c, 0x2d, 0x6d, 0x2c, 0x57, 0x00, 0xd9,
    0x3b, 0xd8, 0xf0, 0x5a, 0x2f, 0x06, 0x63, 0x5e, 0x8f, 0xcb, 0xcc, 0x7d, 0xb1, 0x4c, 0xe0, 0xd6,
    0x96, 0x92, 0xfa, 0xdd, 0x00, 0x76, 0x5b, 0xd9, 0x6e, 0x80, 0x3e, 0xc8, 0x28, 0x0f, 0x92, 0x71,
    0xd6, 0xf1, 0xd5, 0xc3, 0x9e, 0xdc, 0x70, 0x7f, 0xca, 0x30, 0x34, 0xc6, 0x4a, 0x1b, 0x4d, 0x4c,
    0x66, 0xf0, 0xde, 0x05, 0x20, 0x0d, 0x6c, 0x13, 0xbf, 0x5e, 0xb9, 0xfe, 0xce, 0x5d, 0x10, 0x11,
    0x12, 0x78, 0x63, 0x90, 0xa5, 0xbb, 0xef, 0x69, 0x26, 0xfe, 0x48, 0xec, 0xe5, 0x31, 0xc6, 0xc1,
    0x22, 0x95, 0xbc, 0x3a, 0x78, 0xa6, 0xe4, 0x08, 0x35, 0xcd, 0x1a, 0xc6, 0xca, 0x03, 0xa3, 0xb9,
    0x7c, 0x80, 0x62, 0xbc, 0x83, 0x09, 0x2a, 0x07, 0x1e, 0x77, 0x86, 0xba, 0x8b, 0x82, 0x61, 0x83,
    0x2f, 0x9d, 0xef, 0xe3, 0xba, 0xce, 0x49, 0xdb, 0x55, 0xdf, 0x44, 0x0f, 0xb0, 0xc8, 0xf8, 0xd1,
    0x8f, 0xab, 0x23, 0x21, 0x4c, 0xd7, 0x4e, 0x88, 0x99, 0x55, 0xe4, 0xbe, 0x78, 0xa9, 0x86, 0x70,
    0x3a, 0x9a, 0x85, 0xba, 0x64, 0x45, 0x77, 0xdb, 0x08, 0x56, 0xd7, 0x81, 0xda, 0x5d, 0xd4, 0x3f,
    0xd4, 0xdf, 0x97, 0x3a, 0x67, 0xa7, 0x3e, 0x8b, 0x29, 0xa1, 0x94, 0x03, 0x13, 0xce, 0xd5, 0xdd,
    0x49, 0x02, 0x7b, 0x80, 0x5a, 0xdd, 0x01, 0x70, 0x8e, 0x63, 0xec, 0x54, 0xcb, 0xb8, 0x01, 0x65,
    0x34, 0x9b, 0xa6, 0x33, 0x9f, 0xfd, 0x48, 0x32, 0x36, 0x1a, 0x57, 0x2e, 0x79, 0x4f, 0x95, 0xff,
    0x97, 0x00, 0xf4, 0x3b, 0x66, 0xc6, 0x19, 0x63, 0xb0, 0xf8, 0x7d, 0x97, 0x93, 0xc3, 0x28, 0xe0,
    0x38, 0xe4, 0x75, 0xaf, 0xaf, 0xfd, 0x30, 0xc0, 0x3d, 0xf9, 0x84, 0xc5, 0x2d, 0x36, 0x6d, 0xf0,
    0x52, 0x20, 0x66, 0x76, 0x13, 0xa8, 0xcf, 0x02, 0x33, 0x5e, 0xbd, 0x98, 0x4a, 0x81, 0x64, 0x02,
    0x77, 0x2f
  ).map(_.toByte)
}